﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using LINQPad.Extensibility.DataContext;
using Telerik.OpenAccess.Metadata;

namespace LINQPad.OpenAccess.Converters
{
    using LINQPad.OpenAccess.Helpers;
    using MultiplicityTuple = Tuple<Multiplicity, Multiplicity>;

    /// <summary>
    /// AssociationMultiplicity to ExplorerIcon converter - static members.
    /// </summary>
    partial class AssociationMultiplicityToExplorerIconConverter
    {
        #region Static

        #region - Private

        #region - Vars

        [DebuggerBrowsable( DebuggerBrowsableState.Never )]
        private static readonly IDictionary<MultiplicityTuple, ExplorerIcon> _AssociationIconMap;
        [DebuggerBrowsable( DebuggerBrowsableState.Never )]
        private static AssociationMultiplicityToExplorerIconConverter _DefaultInstance;

        #endregion

        #region - Constructor

        /// <summary>
        /// Initializes the <see cref="SchemaBuildContext" /> class.
        /// </summary>
        static AssociationMultiplicityToExplorerIconConverter( )
        {
            _AssociationIconMap = BuildAssociationExplorerIconMap( );
            _DefaultInstance = new AssociationMultiplicityToExplorerIconConverter( );
        }

        #endregion

        #region - Functions

        /// <summary>
        /// Builds the explorer icon map for associations.
        /// </summary>
        /// <returns>
        /// The icon map.
        /// </returns>
        private static IDictionary<MultiplicityTuple, ExplorerIcon> BuildAssociationExplorerIconMap( )
        {
            var map = new Dictionary<MultiplicityTuple, ExplorerIcon>( );
            map.Add( new MultiplicityTuple( Multiplicity.Many, Multiplicity.Many ), ExplorerIcon.ManyToMany );

            map.Add( new MultiplicityTuple( Multiplicity.Many, Multiplicity.One ), ExplorerIcon.ManyToOne );
            map.Add( new MultiplicityTuple( Multiplicity.Many, Multiplicity.ZeroOrOne ), ExplorerIcon.ManyToOne );
            map.Add( new MultiplicityTuple( Multiplicity.One, Multiplicity.Many ), ExplorerIcon.OneToMany );
            map.Add( new MultiplicityTuple( Multiplicity.ZeroOrOne, Multiplicity.Many ), ExplorerIcon.OneToMany );

            map.Add( new MultiplicityTuple( Multiplicity.One, Multiplicity.One ), ExplorerIcon.OneToOne );
            map.Add( new MultiplicityTuple( Multiplicity.ZeroOrOne, Multiplicity.ZeroOrOne ), ExplorerIcon.OneToOne );
            map.Add( new MultiplicityTuple( Multiplicity.One, Multiplicity.ZeroOrOne ), ExplorerIcon.OneToOne );
            map.Add( new MultiplicityTuple( Multiplicity.ZeroOrOne, Multiplicity.One ), ExplorerIcon.OneToOne );

            return map;
        }

        #endregion

        #endregion

        #region Public

        #region - Functions

        /// <summary>
        /// Gets the explorer icon for association.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="target">The target.</param>
        /// <param name="fallbackIcon">The fallback icon.</param>
        /// <returns>
        /// The explorer icon or <param name="fallbackIcon" />.
        /// </returns>
        public static ExplorerIcon GetExplorerIconForAssociation( Multiplicity source, Multiplicity target, ExplorerIcon fallbackIcon = ExplorerIcon.Column )
        {
            var tuple = new MultiplicityTuple( source, target );
            ExplorerIcon explorerIcon;
            if ( _AssociationIconMap.TryGetValue( tuple, out explorerIcon ) )
                return explorerIcon;
            return fallbackIcon;
        }

        #endregion

        #region - Properties

        /// <summary>
        /// Gets the default converter instance.
        /// </summary>
        /// <value>
        /// The default converter instance.
        /// </value>
        public static AssociationMultiplicityToExplorerIconConverter Default
        {
            get
            {
                return _DefaultInstance;
            }
            set
            {
                Guard.ArgumentNotNull( value, "value" );
                _DefaultInstance = value;
            }
        }

        #endregion

        #endregion

        #endregion

    }
}
